﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.IO;
using System.Security.Permissions;
using System.Threading;
using System.Threading.Tasks;
using System.Collections;
using System.Runtime.InteropServices;
using DropNet;
using DropNet.Models;
using Microsoft.Win32;
using System.Diagnostics;
using RestSharp.Extensions;
using System.Net;
namespace sync
{
    public partial class frmMain : Form
    {

        sClientInfo sci;
        sMessage sms;
        public frmMain()
        {
            InitializeComponent();
            sci = new sClientInfo();
            sms = new sMessage();
        }
        FileSystemWatcher _watcher;
        private DropNetClient _client;
        string configFile = "config.ini";
        string configFileTmp = "config1.ini";
        string logFile = "log.ini";
        string logSVFile = "logSV.ini";
        string client = "1";
        string cursor = "";
        bool syncDataToSV = true;
        bool syncDataToCL = true;
        bool syncD = true;
        List<string> listChange = new List<string>();
        List<string> listlogSV = new List<string>();
        string apiKey = "blglx3u2bqm0je5", apiSecret = "ss27q9hcd9zqayr",
               userToken = "nhanjusfqv14h2z", userSecret = "hf5q5co1uu1vuxj";


        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]

        private void thrdCheck()
        {
          new sFileMethods().checkFileExist(configFile);
            using (StreamReader sr = new StreamReader(configFile))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    string path;
                    if (line.StartsWith("path :"))
                    {
                        path = line.Substring(line.LastIndexOf("path :") + 6, line.Length - line.LastIndexOf("path :") - 6);

                    }
                }
            }
        }
        //Monitor Metadata change with given path
        private void watcherFoler(string folder)
        {
            // Create a new FileSystemWatcher and set its properties.
            _watcher = new FileSystemWatcher();
            _watcher.Path = folder;
            /* Watch for changes in LastAccess and LastWrite times, and
               the renaming of files or directories. */
            _watcher.NotifyFilter =
                NotifyFilters.Attributes
                | NotifyFilters.CreationTime |
                 NotifyFilters.LastAccess
                | NotifyFilters.Size | NotifyFilters.Security
                |
            NotifyFilters.LastWrite |
            NotifyFilters.FileName | NotifyFilters.DirectoryName;
            // Filter files.
            _watcher.Filter = "*";
            _watcher.IncludeSubdirectories = true;
            // Add event handlers.
            _watcher.Changed += new FileSystemEventHandler(OnChanged);
            _watcher.Created += new FileSystemEventHandler(OnCreate);
            _watcher.Deleted += new FileSystemEventHandler(OnDelete);
            _watcher.Renamed += new RenamedEventHandler(OnRenamed);
            // Begin watching.
            _watcher.EnableRaisingEvents = true;
        }
        private void disableWatcher()
        {
            _watcher.EnableRaisingEvents = false;
            _watcher.Changed -= new FileSystemEventHandler(OnChanged);
            _watcher.Created -= new FileSystemEventHandler(OnCreate);
            _watcher.Deleted -= new FileSystemEventHandler(OnDelete);
            _watcher.Renamed -= new RenamedEventHandler(OnRenamed);
            _watcher.Dispose();
        }
        private void enableWatcher()
        {
            _watcher.Changed += new FileSystemEventHandler(OnChanged);
            _watcher.Created += new FileSystemEventHandler(OnCreate);
            _watcher.Deleted += new FileSystemEventHandler(OnDelete);
            _watcher.Renamed += new RenamedEventHandler(OnRenamed);
            _watcher.EnableRaisingEvents = true;
        }
        //Load sync path to listview
        private void loadListFolder()
        {
            new sFileMethods().checkFileExist(configFile);
            int count = 0;
            using (StreamReader sr = new StreamReader(configFile))
            {
                string line;
                listFolder.Items.Clear();
                while ((line = sr.ReadLine()) != null)
                {
                    string path;
                    if (line.StartsWith("path :"))
                    {
                        path = line.Substring(line.LastIndexOf("path :") + 6, line.Length - line.LastIndexOf("path :") - 6);

                        listFolder.Items.Add(path, count.ToString());
                        if (Directory.Exists(path))
                        {
                            
                            sci.pathClient = path;
                            watcherFoler(path);
                        }
                        else
                            sms.error=(path + " does not exist !");
                        count++;
                    }
                }
                if (count == 0)
                    sms.error = "File config is empty";
            }

        }
      
        //Write all file and folder to log.ini when copy event is raised
        private void thrdCopyFolder(string path)
        {
            pathCopyDir = path;
            Thread thrd = new Thread(copyFolder);
            thrd.Start();
        }
        string pathCopyDir;
        private void copyFolder()
        {
            foreach (var folder in Directory.GetDirectories(pathCopyDir, "*", SearchOption.AllDirectories))
            {
                string eName = folder.Substring(folder.LastIndexOf("\\") + 1);
                string line = "|CL|" + client + "|DT|" + DateTime.Now + "|CT|" + "Created" + "|FP|" + folder + "|FN|" + eName;
                listChange.Add(line);
            }
            foreach (var file in Directory.GetFiles(pathCopyDir, "*", SearchOption.AllDirectories))
            {
                string eName = file.Substring(file.LastIndexOf("\\") + 1);
                string line = "|CL|" + client + "|DT|" + DateTime.Now + "|CT|" + "Created" + "|FP|" + file + "|FN|" + eName;
                listChange.Add(line);
            }
        }
        // Load data from server
        private void loadServer()
        {
            _client = new DropNetClient(apiKey, apiSecret);
            _client.UserLogin = new UserLogin { Token = userToken, Secret = userSecret };
        }

        private void createChangeEvent(int idx, string[] arrayLog, string changeType)
        {
            string fullPath = arrayLog[idx].Substring(arrayLog[idx].LastIndexOf("|FP|") + 4, arrayLog[idx].LastIndexOf("|FN|") - arrayLog[idx].LastIndexOf("|FP|") - 4);
            string fileName = arrayLog[idx].Substring(arrayLog[idx].LastIndexOf("|FN|") + 4, arrayLog[idx].Length - arrayLog[idx].LastIndexOf("|FN|") - 4);
            string rootSV = new sClientInfo().pathClient.Replace("\\", "/");
            string fullPathSV = fullPath.Substring(rootSV.Length, fullPath.Length - rootSV.Length).Replace("\\", "/");
            string pathSV = fullPathSV.Substring(0, fullPathSV.Length - fileName.Length);
            string strDT = arrayLog[idx].Substring(arrayLog[idx].LastIndexOf("|DT|") + 4, arrayLog[idx].LastIndexOf("|CT|") - arrayLog[idx].LastIndexOf("|DT|") - 4);
            DateTime dtModify = DateTime.Now;
            try
            {
                dtModify = DateTime.Parse(strDT);
            }
            catch (Exception ex)
            {
                sms.error=("CreateChangEvent: \n Datetime parse error :" + "\n" + ex.Message);
            }
            string changeTypeI = "", fullPathI = "";
            List<string> listA = new List<string>();
            for (int i = 0; i < arrayLog.Length; i++)
            {
                if (!arrayLog[i].Contains("|OFP|") && arrayLog[i].Trim() != "")
                {
                    changeTypeI = arrayLog[i].Substring(arrayLog[i].LastIndexOf("|CT|") + 4, arrayLog[i].LastIndexOf("|FP|") - arrayLog[i].LastIndexOf("|CT|") - 4);
                    fullPathI = arrayLog[i].Substring(arrayLog[i].LastIndexOf("|FP|") + 4, arrayLog[i].LastIndexOf("|FN|") - arrayLog[i].LastIndexOf("|FP|") - 4);
                    if (fullPath == fullPathI && (changeTypeI == "Changed" || changeTypeI == "Created"))
                    {
                        listA.Add(arrayLog[i]);// if same full path and changetype=change or create,adding to listA
                    }
                }

            }
            #region "Create file"
            if (File.Exists(fullPath))
            {
                //Async --- Upload file to Dropbox
                syncDataToSV = false;
                bool fileExist = false;
                _client.SearchAsync(fileName, pathSV,
                    (response) =>
                    {
                        MetaData[] fileSearch = response.ToArray();
                        for (int i = 0; i < fileSearch.Count(); i++)
                        {
                            if (!fileSearch[i].Is_Dir)
                            {
                                if (fileSearch[i].Path.ToLower() == fullPathSV.ToLower())
                                    fileExist = true;
                            }
                        }
                        if (!fileExist || fileSearch[0].ModifiedDate < dtModify)
                        {
                            // Upload file to Server with async method
                            _client.UploadFileAsync(pathSV, fileName, File.ReadAllBytes(fullPath),
                            (responseUpload) =>
                            {
                                //Show message when upload success
                                sms.success = "\"" + fileName + "\"" + "was added";
                                //---Remove line when file upload success from file listlog
                                for (int i = 0; i < listA.Count; i++)
                                {
                                    arrayLog = arrayLog.Where(w => w != listA[i]).ToArray();
                                }
                                //----------------------------
                                syncDataToSV = true;
                                new sRegistryMethods().Registry_Set("Cursor", _client.GetDelta(cursor).Cursor);
                            },
                            (error) =>
                            {
                                //show error message if file upload fail
                                sms.error = "Create File : upload " + fileName + " fail  \n" + error.Message;
                                syncDataToSV = true;
                            });
                        }
                        else
                        {
                            for (int i = 0; i < listA.Count; i++)
                            {
                                arrayLog = arrayLog.Where(w => w != listA[i]).ToArray();
                            }
                            //----------------------------

                            syncDataToSV = true;
                        }
                    },
                        (error) =>
                        {
                            sms.error = error.Message;
                            syncDataToSV = true;
                        });
            }
            #endregion
            #region "Create folder"
            else
                if (Directory.Exists(fullPath) && changeType == "Created")
                {
                    // Async--- Create folder on dropbox
                    bool folderExist = false;
                    syncDataToSV = false;
                    _client.SearchAsync(fileName, pathSV,
                   (responseSearch) =>
                   {
                       MetaData[] folderSearch = responseSearch.ToArray();
                       for (int i = 0; i < folderSearch.Count(); i++)
                       {
                           if (folderSearch[i].Is_Dir)
                           {
                               if (folderSearch[i].Path == fullPathSV)
                                   folderExist = true;
                           }
                       }
                       if (!folderExist)
                       {
                           //Async --- Upload file to Dropbox
                           _client.CreateFolderAsync(fullPathSV,
                           (responseUpload) =>
                           {
                               try
                               {
                                   //Show message when upload success
                                   notifyIcon1.ShowBalloonTip(2, "Sync", "\"" + fileName + "\"" + " was created", ToolTipIcon.Info);
                                   //---Remove line from file log
                                   //----------------------------
                                   for (int i = 0; i < listA.Count; i++)
                                   {
                                       arrayLog = arrayLog.Where(w => w != listA[i]).ToArray();
                                   }
                                   new sRegistryMethods().Registry_Set("Cursor", _client.GetDelta(cursor).Cursor);
                               }
                               catch (Exception ex)
                               {
                                   showNotify(lineNB() + "\n" + ex.Message);
                               }
                               syncDataToSV = true;
                           },
                           (error) =>
                           {
                               //Do something on error
                               notifyIcon1.ShowBalloonTip(2, "Sync", "Create folder| upload " + fileName + " fail  \n" + error.Message, ToolTipIcon.Info);
                               syncDataToSV = true;
                           });
                       }
                       else
                       {
                           try
                           {
                               arrayLog = arrayLog.Where(w => w != arrayLog[idx]).ToArray();
                           }
                           catch (Exception ex)
                           {
                               showNotify(lineNB() + "\n" + ex.Message);
                           }
                           syncDataToSV = true;
                       }

                   },
                   (error) =>
                   {

                       notifyIcon1.ShowBalloonTip(2, "Sync", "Create folder | Search folder fail :\n" + error.Message, ToolTipIcon.Info);
                       syncDataToSV = true;
                   });

                }

                else
                {
                    try
                    {
                        for (int i = 0; i < listA.Count; i++)
                        {
                            arrayLog = arrayLog.Where(w => w != listA[i]).ToArray();
                        }
                    }
                    catch (Exception ex)
                    {
                        showNotify(lineNB() + "\n" + ex.Message);
                    }

                    syncDataToSV = true;
                }
            #endregion
        }
        private void deleteEvent(int idx, string[] arrayLog)
        {
            string fullPath = arrayLog[idx].Substring(arrayLog[idx].LastIndexOf("|FP|") + 4, arrayLog[idx].LastIndexOf("|FN|") - arrayLog[idx].LastIndexOf("|FP|") - 4);
            string fileName = arrayLog[idx].Substring(arrayLog[idx].LastIndexOf("|FN|") + 4, arrayLog[idx].Length - arrayLog[idx].LastIndexOf("|FN|") - 4);
            string rootSV = new sClientInfo().pathClient.Replace("\\", "/");
            string fullPathSV = fullPath.Substring(rootSV.Length, fullPath.Length - rootSV.Length).Replace("\\", "/");
            string pathSV = fullPathSV.Substring(0, fullPathSV.Length - fileName.Length);
            string changeTypeI = "",
                fullPathI = "",
                getDir = Path.GetDirectoryName(fullPath),
                getDirI = "";
            List<string> listDirDel = new List<string>();
            if (!Directory.Exists(getDir))
                for (int i = 0; i < arrayLog.Length; i++)
                {
                    if (!arrayLog[i].Contains("|OFP|") && arrayLog[i].Trim() != "")
                    {
                        changeTypeI = arrayLog[i].Substring(arrayLog[i].LastIndexOf("|CT|") + 4, arrayLog[i].LastIndexOf("|FP|") - arrayLog[i].LastIndexOf("|CT|") - 4);
                        fullPathI = arrayLog[i].Substring(arrayLog[i].LastIndexOf("|FP|") + 4, arrayLog[i].LastIndexOf("|FN|") - arrayLog[i].LastIndexOf("|FP|") - 4);
                        getDirI = Path.GetDirectoryName(fullPathI);
                        if (getDir == getDirI || fullPathI.Contains(getDir))
                        {
                            listDirDel.Add(arrayLog[i]);// if same full path and changetype=change or create,adding to listA
                        }
                    }

                }
            {
                // Async---Delete file on Dropbox
                bool fileSearchExist = false;
                syncDataToSV = false;
                //Check filename exist in Server

                _client.SearchAsync(fileName, pathSV,
                (responseSearch) =>
                {
                    MetaData[] fileSearch = responseSearch.ToArray();
                    for (int i = 0; i < fileSearch.Count(); i++)
                    {
                        if (!fileSearch[i].Is_Dir)
                        {
                            if (fileSearch[i].Path.ToLower() == fullPathSV.ToLower())
                                fileSearchExist = true;
                        }
                        else
                            if (fileSearch[i].Is_Dir)
                            {
                                if (fileSearch[i].Path.ToLower() == fullPathSV.ToLower())
                                    fileSearchExist = true;
                            }
                    }
                    if (fileSearchExist)
                    {
                        if (!Directory.Exists(getDir))
                            fullPathSV = pathSV;
                        _client.DeleteAsync(fullPathSV, (response) =>
                        {
                            //Do something
                            try
                            {
                                notifyIcon1.ShowBalloonTip(2, "Sync", "Deleted " + fileName, ToolTipIcon.Info);
                                //---Remove line from file log
                                if (!Directory.Exists(getDir))
                                {
                                    for (int i = 0; i < listDirDel.Count; i++)
                                    {
                                        arrayLog = arrayLog.Where(w => w != listDirDel[i]).ToArray();
                                    }
                                }
                                else
                                    arrayLog = arrayLog.Where(w => w != arrayLog[idx]).ToArray();
                                new sRegistryMethods().Registry_Set("Cursor", _client.GetDelta(cursor).Cursor);
                                syncDataToSV = true;
                            }
                            catch (Exception ex)
                            {
                                showNotify(lineNB() + "\n" + ex.Message); syncDataToSV = true;
                            }
                            
                        },
                            (error) =>
                            {
                                //Do something on error
                                showNotify(lineNB() + "\n" + error.Message);
                                syncDataToSV = true;
                            });
                    }
                    else
                    {
                        try
                        {
                            arrayLog = arrayLog.Where(w => w != arrayLog[idx]).ToArray();
                            syncDataToSV = true;
                        }
                        catch (Exception ex)
                        {
                            showNotify(lineNB() + "\n" + ex.Message); syncDataToSV = true;
                        }
                        syncDataToSV = true;
                    }
                },
                    (error) =>
                    {

                        showNotify(lineNB() + "\n" + error.Message);
                        syncDataToSV = true;
                    });

            }
        }
        private void renameEvent(int idx, string[] arrayLog)
        {
            string oldfullPath = arrayLog[idx].Substring(arrayLog[idx].LastIndexOf("|OFP|") + 5, arrayLog[idx].LastIndexOf("|OFN|") - arrayLog[idx].LastIndexOf("|OFP|") - 5);
            string oldFileName = arrayLog[idx].Substring(arrayLog[idx].LastIndexOf("|OFN|") + 5, arrayLog[idx].LastIndexOf("|NFP|") - arrayLog[idx].LastIndexOf("|OFN|") - 5);


            string newFullPath = arrayLog[idx].Substring(arrayLog[idx].LastIndexOf("|NFP|") + 5, arrayLog[idx].LastIndexOf("|NFN|") - arrayLog[idx].LastIndexOf("|NFP|") - 5);
            string newFileName = arrayLog[idx].Substring(arrayLog[idx].LastIndexOf("|NFN|") + 5, arrayLog[idx].Length - arrayLog[idx].LastIndexOf("|NFN|") - 5);

            //Async --- Upload file to Dropbox
            string rootSV = new sClientInfo().pathClient.Replace("\\", "/");
            string oldFullPathSV = oldfullPath.Substring(rootSV.Length, oldfullPath.Length - rootSV.Length).Replace("\\", "/");
            string oldPathSV = oldFullPathSV.Substring(0, oldFullPathSV.Length - oldFileName.Length);
            string newFullPathSV = newFullPath.Substring(rootSV.Length, newFullPath.Length - rootSV.Length).Replace("\\", "/");
            string newPathSV = newFullPathSV.Substring(0, newFullPathSV.Length - newFileName.Length);
            // Async---Delete file on Dropbox
            #region "Rename file"
            if (File.Exists(newFullPath))
            {
                syncDataToSV = false;
                bool oldFileSVExist = false;

                _client.SearchAsync(oldFileName, oldPathSV,
                    (responseSearchFile) =>
                    {
                        MetaData[] fileSearch = responseSearchFile.ToArray();
                        for (int i = 0; i < fileSearch.Count(); i++)
                        {
                            if (!fileSearch[i].Is_Dir)
                            {
                                if (fileSearch[i].Path.ToLower() == oldFullPathSV.ToLower())
                                    oldFileSVExist = true;
                            }
                        }
                        if (oldFileSVExist)
                        {
                            bool newFileSVExist = false;
                            _client.SearchAsync(newFileName, newPathSV,
                                (response1) =>
                                //Check filename exist in Server
                                {
                                    MetaData[] file = response1.ToArray();
                                    for (int i = 0; i < file.Count(); i++)
                                    {
                                        if (!file[i].Is_Dir)
                                        {
                                            if (file[i].Path == newFullPathSV)
                                                newFileSVExist = true;
                                        }
                                    }
                                    if (newFileSVExist)
                                    {
                                        _client.DeleteAsync(newFullPathSV, (response) =>
                                        {
                                            //Do something
                                            new sRegistryMethods().Registry_Set("Cursor", _client.GetDelta(cursor).Cursor);
                                        },
                                          (error) =>
                                          {
                                              //Do something on error
                                              notifyIcon1.ShowBalloonTip(2, "Sync", "Rename | Delete new file : " + newFileName + " fail :\n" + error.Message, ToolTipIcon.Info);
                                              syncDataToSV = true;
                                          });
                                    }
                                    _client.MoveAsync(oldFullPathSV, newFullPathSV,
                                     (response) =>
                                     {
                                         //Do something with response
                                         try
                                         {
                                             notifyIcon1.ShowBalloonTip(2, "Sync", newFileName + "was renamed success", ToolTipIcon.Info);

                                             //---Remove line from file log
                                             arrayLog = arrayLog.Where(w => w != arrayLog[idx]).ToArray();
                                             //----------------------------
                                             new sRegistryMethods().Registry_Set("Cursor", _client.GetDelta(cursor).Cursor);
                                         }
                                         catch (Exception ex)
                                         {
                                             showNotify(lineNB() + "\n" + ex.Message);
                                         }
                                         syncDataToSV = true;
                                     },
                                     (error) =>
                                     {
                                         //Do something on error
                                         showNotify(lineNB() + "\n" + error.Message);
                                         syncDataToSV = true;
                                     });
                                },
                                 (error) =>
                                 {
                                     //Do something on error
                                     showNotify(lineNB() + "\n" + error.Message);
                                     syncDataToSV = true;
                                 });
                        }
                        else
                        {

                            bool fileExist = false;
                            _client.SearchAsync(newFileName, newPathSV,
                                (responseSearchNF) =>
                                {
                                    MetaData[] file = responseSearchNF.ToArray();
                                    //Check filename exist in Server
                                    for (int i = 0; i < file.Count(); i++)
                                    {
                                        if (!file[i].Is_Dir)
                                        {
                                            if (file[i].Path == newFullPath)
                                                fileExist = true;
                                        }
                                    }
                                    if (fileExist)
                                    {
                                        _client.DeleteAsync(newFullPathSV, (response) =>
                                        {
                                            //Do something
                                            new sRegistryMethods().Registry_Set("Cursor", _client.GetDelta(cursor).Cursor);
                                        },
                                         (error) =>
                                         {
                                             //Do something on error
                                             showNotify(lineNB() + "\n" + error.Message);
                                         });
                                    }

                                    _client.UploadFileAsync(newPathSV, newFileName, File.ReadAllBytes(newFullPath),
                                    (responseUpload) =>
                                    {
                                        //Show message when upload success
                                        try
                                        {
                                            notifyIcon1.ShowBalloonTip(2, "Sync", " Renamed " + oldFileName + " => " + newFileName, ToolTipIcon.Info);
                                            //---Remove line from file log
                                            arrayLog = arrayLog.Where(w => w != arrayLog[idx]).ToArray();
                                            //----------------------------
                                            new sRegistryMethods().Registry_Set("Cursor", _client.GetDelta(cursor).Cursor);
                                        }
                                        catch (Exception ex)
                                        {
                                            showNotify(lineNB() + "\n" + ex.Message);
                                        }
                                        syncDataToSV = true;
                                    },
                                    (error) =>
                                    {
                                        //Do something on error
                                        showNotify(lineNB() + "\n" + error.Message);
                                        syncDataToSV = true;
                                    });

                                },
                             (error) =>
                             {
                                 showNotify(lineNB() + "\n" + error.Message);
                                 syncDataToSV = true;
                             });

                        }
                    },
                        (error) =>
                        {
                            showNotify(lineNB() + "\n" + error.Message);
                            syncDataToSV = true;
                        });
            }

            #endregion
            #region "Rename folder"
            if (Directory.Exists(newFullPath))
            {
                // Check folder Exist in server
                bool folderExist = false;
                syncDataToSV = false;
                _client.SearchAsync(newFileName, newPathSV,
                    (response1) =>
                    {
                        MetaData[] folderSearch = response1.ToArray();
                        for (int i = 0; i < folderSearch.Count(); i++)
                        {
                            if (folderSearch[i].Is_Dir)
                            {
                                if (folderSearch[i].Path == newFullPathSV)
                                    folderExist = true;
                            }
                        }

                        if (folderExist == false)
                        {
                            _client.MoveAsync(oldFullPathSV, newFullPathSV,
                                 (response) =>
                                 {
                                     //Do something with response
                                     try
                                     {
                                         notifyIcon1.ShowBalloonTip(2, "Sync", newFileName + " was renamed success", ToolTipIcon.Info);
                                         //remove line
                                         arrayLog = arrayLog.Where(w => w != arrayLog[idx]).ToArray();
                                         new sRegistryMethods().Registry_Set("Cursor", _client.GetDelta(cursor).Cursor);
                                     }
                                     catch (Exception ex)
                                     {
                                         showNotify(lineNB() + "\n" + ex.Message);
                                     }
                                     syncDataToSV = true;
                                 },
                                 (error) =>
                                 {
                                     //Do something on error
                                     syncDataToSV = true;
                                     showNotify(lineNB() + "\n" + error.Message);
                                 });
                        }
                    },
                (error) =>
                {
                    showNotify(lineNB() + "\n" + error.Message);
                    syncDataToSV = true;
                });

            }
            else
            {
                arrayLog = arrayLog.Where(w => w != arrayLog[idx]).ToArray();
                syncDataToSV = true;
            }
            #endregion
        }
        //Add change file on Server to List
        private void addTolistlogSV()
        {
            cursor =new sRegistryMethods(). Registry_Get("Cursor");
            DeltaPage detaPage = _client.GetDelta(cursor);
            cursor = detaPage.Cursor;
            if (detaPage.Entries.Count > 0)
            {
                int countD = 0;
                foreach (DeltaEntry de in detaPage.Entries)
                {
                    if (countD == detaPage.Entries.Count - 1)
                    {
                       new sRegistryMethods().Registry_Set("Cursor", cursor);
                    }
                    string isDir = "|ID|null",
                    dateModify = "",
                    fileName = de.Path.Substring(de.Path.LastIndexOf("/") + 1, de.Path.Length - de.Path.LastIndexOf("/") - 1);
                    if (de.MetaData != null)
                    {
                        isDir = "|ID|Is_Dir:" + de.MetaData.Is_Dir.ToString();
                        dateModify = "|DT|" + de.MetaData.ModifiedDate.ToString();
                    }
                    listlogSV.Add("|FN|" + fileName + "|FP|" + de.Path + isDir + dateModify);
                    countD++;
                }
            }
            if (detaPage.Entries.Count == 0)
                return;
        }
        int countSTC = 0;
        private  bool syncToClient()
        {
            
            sFileMethods fl = new sFileMethods();
            if (fl.IsFileLocked(logSVFile))
                return true;
            List<string> listLog = listlogSV;
            if (listLog.Count == 0)
                return true;

            string line = "";
            //for (int i = 0; i < listLog.Count; i++)
            {
                if (countSTC >= listLog.Count - 1)
                    countSTC = 0;
                line = listlogSV[countSTC];
                if (line.Trim() != ""||line!="null")
                {

                    string fullPathSV = line.Substring(line.LastIndexOf("|FP|") + 4, line.LastIndexOf("|ID|") - line.LastIndexOf("|FP|") - 4),
                     fullPathCL = sci.pathClient + fullPathSV.Replace("/", @"\"),
                     fileName = line.Substring(line.LastIndexOf("|FN|") + 4, line.LastIndexOf("|FP|") - line.LastIndexOf("|FN|") - 4),
                     pathSV = fullPathSV.Substring(0, fullPathSV.Length - fileName.Length),
                     meta = "null", stdateModify = "";
                    DateTime dateModify = DateTime.Now;
                    if (line.Contains("|DT|"))
                    {
                        meta = line.Substring(line.LastIndexOf("|ID|") + 4, line.LastIndexOf("|DT|") - line.LastIndexOf("|ID|") - 4);
                        stdateModify = line.Substring(line.LastIndexOf("|DT|") + 4, line.Length - line.LastIndexOf("|DT|") - 4);
                        try
                        {
                            dateModify = DateTime.Parse(stdateModify);
                        }
                        catch (Exception ex)
                        {
                            sms.error=("Datetime parse fail :" + "\n" + ex.Message);
                        }
                    }


                    if (meta == "null")//delete file or folder from client
                    {
                        if (File.Exists(fullPathCL))//if file eixist in client
                        {
                            syncDataToCL = false;
                            try
                            {
                                // Delete file from Client
                                File.Delete(fullPathCL);
                                listlogSV = listlogSV.Where(w => w != line).ToList();
                                new sRegistryMethods().Registry_Set("Cursor", cursor);
                                syncDataToCL = true;
                            }
                            catch (Exception ex)
                            {
                                sms.error = "Delete \"" + fileName + "\" fail \n" + ex.Message;
                                countSTC++;
                                syncDataToCL = true;
                            }


                        }
                        if (Directory.Exists(fullPathCL))//if folder exist in client
                        {
                            if (Directory.GetFiles(fullPathCL).Length == 0)
                            {
                                syncDataToCL = false;
                                try
                                {
                                    //Delete folder from Client
                                    Directory.Delete(fullPathCL);
                                    listlogSV = listlogSV.Where(w => w != line).ToList();
                                    new sRegistryMethods().Registry_Set("Cursor", cursor);
                                    syncDataToCL = true;
                                }
                                catch (Exception ex)
                                {
                                    sms.error = "Delete \"" + fileName + "\" fail \n" + ex.Message;
                                    countSTC++;
                                    syncDataToCL = true;
                                }
                            }
                        }
                        else//if file or folder not exist in client
                        {
                                listlogSV = listlogSV.Where(w => w != line).ToList();
                                new sRegistryMethods().Registry_Set("Cursor", cursor);
                                syncDataToCL = true;
                        }
                    }
                    else
                    {
                        if (meta == "Is_Dir:False")
                        {
                            syncDataToCL = false;
                            bool fileExist = false;
                            _client.SearchAsync(fileName, pathSV,
                          (responseS) =>
                          {
                              MetaData[] fileSearch = responseS.ToArray();
                              for (int i = 0; i < fileSearch.Count(); i++)
                              {
                                  if (!fileSearch[i].Is_Dir)
                                  {
                                      if (fileSearch[i].Path.ToLower() == fullPathSV.ToLower())
                                          fileExist = true;
                                  }
                              }
                              if (!fileExist)
                              {
                                      listlogSV = listlogSV.Where(w => w != line).ToList();
                                      new sRegistryMethods().Registry_Set("Cursor", cursor);
                                      syncDataToCL = true;
                              }
                              else
                              {
                                  _client.GetFileAsync(fullPathSV,
                                   (response) =>
                                   {
                                       try
                                       {
                                           if (!File.Exists(fullPathCL))
                                               new sFileMethods().AppendAllBytes(fullPathCL, response.RawBytes);
                                           else
                                           {
                                               if (File.GetLastWriteTime(fullPathCL) < dateModify)
                                               {
                                                   //if (File.ReadAllBytes(fullPathCL).Length == response.RawBytes.Length)
                                                   {
                                                       File.Delete(fullPathCL);
                                                       new sFileMethods().AppendAllBytes(fullPathCL, response.RawBytes);
                                                   }
                                               }
                                           }
                                           listlogSV = listlogSV.Where(w => w != line).ToList();
                                           new sRegistryMethods().Registry_Set("Cursor", cursor);
                                       }
                                       catch (Exception ex)
                                       {
                                           sms.error = "Getfile |Delete  \"" + fileName + "\" fail \n" + ex.Message;
                                           countSTC++;
                                       }
                                       syncDataToCL = true;
                                   },
                                       (error) =>
                                       {
                                           sms.error = "Download \"" + fileName + "\" fail \n" + error.Message;
                                           countSTC++;
                                           syncDataToCL = true;
                                       });
                              }
                          },
                          (error) =>
                          {
                              sms.error = "Server not response \n" + error.Message;
                              countSTC++;
                              syncDataToCL = true;
                          });


                        }
                        else
                        {
                            if (!Directory.Exists(fullPathCL))
                            {
                                syncDataToCL = false;
                                try
                                {

                                    Directory.CreateDirectory(fullPathCL);
                                    new sRegistryMethods().Registry_Set("Cursor", cursor);
                                    syncDataToCL = true;
                                }
                                catch (Exception ex)
                                {
                                    sms.error = "Create folder \"" + fileName + "\" fail \n" + ex.Message;
                                    countSTC++;
                                    syncDataToCL = true;
                                }
                            }
                            else
                            {
                                listlogSV = listlogSV.Where(w => w != line).ToList();
                                new sRegistryMethods().Registry_Set("Cursor", cursor);
                                syncDataToCL = true;
                            }
                        }
                    }
                }
                else
                {
                    listlogSV = listlogSV.Where(w => w != line).ToList();
                    syncDataToCL = true;
                }
            }
            return syncDataToCL;
        }
        private bool syncToServer()
        {
            sFileMethods fl = new sFileMethods();
            if (fl.IsFileLocked(logFile))
            {
                syncDataToSV = true;
                return true;
            }
            string[] arrayLog;
            {

                arrayLog = listChange.ToArray();
                if (arrayLog.Length == 0)
                {
                    
                    syncDataToSV = true;
                    return true;
                }
                string line;
                int k = 0;
                line = arrayLog[k];
                if (line.Trim() != "")
                {

                    int lineLength = line.Length;
                    string changeType;
                    if (line.Contains("|OFP|"))
                        changeType = line.Substring(line.LastIndexOf("|CT|") + 4, line.LastIndexOf("|OFP|") - line.LastIndexOf("|CT|") - 4);
                    else
                    {
                        changeType = line.Substring(line.LastIndexOf("|CT|") + 4, line.LastIndexOf("|FP|") - line.LastIndexOf("|CT|") - 4);
                    }
                    #region "Created event"
                    if (changeType == "Created" || changeType == "Changed")
                    {
                        createChangeEvent(k, arrayLog, changeType);
                    }
                    #endregion

                    #region "Deleted event"
                    else
                        if (changeType == "Deleted")
                        {
                            deleteEvent(k, arrayLog);
                        }
                    #endregion

                        #region "Renamed event"
                        else
                            if (changeType == "Renamed")
                            {
                                renameEvent(k, arrayLog);
                            }
                        #endregion
                }
                else
                {
                    arrayLog = arrayLog.Where(w => w != line).ToArray();
                    File.WriteAllLines(logFile, arrayLog);
                    syncDataToSV = true;
                }
            }
            //File.Delete(logFile);
            ////File.Move(fileTmp, logFile);
            //thrd.Start();
            return syncDataToSV;
        }
        private async void asyncToClient()
        {
            try
            {
                syncD = false;
                Task t1 = Task.Factory.StartNew(() => addTolistlogSV());
                await t1;
                Task t4 = Task.Factory.StartNew(() => syncToClient());
            }
            catch (Exception ex)
            { showNotify(lineNB() + "\n" + ex.Message); }
        }
        private void showNotify(string s)
        {
            notifyIcon1.ShowBalloonTip(2, "Sync", s, ToolTipIcon.Info);

        }
        private string lineNB()
        {
            StackFrame stackFrame = new StackFrame(1, true);

            string method = stackFrame.GetMethod().ToString();
            int line = stackFrame.GetFileLineNumber();

            return line.ToString() + ":" + method;
        }
        private void btnCheckDel_Click(object sender, EventArgs e)
        {
            string path = @"G:\WORK\Server\02.txt";
            var oldLines = System.IO.File.ReadAllLines(path);
            var newLines = oldLines.Where(line => !line.Contains("b"));
            //System.IO.File.WriteAllLines(path, newLines);
            //FileInfo fi = new FileInfo("config.ini");
            //if (fi.Exists && enable)
            //{
            //    Thread thrd = new Thread(check());
            //    thrd.Start();
            //}
        }
        // Define the event handlers. 
        private void OnChanged(object source, FileSystemEventArgs e)
        {
            try
            {
                string eName = e.Name.Substring(e.Name.LastIndexOf("\\") + 1);
                if (!new sFileMethods().filterFile(eName))
                    return;
                string changeEvent = "|CL|" + client + "|DT|" + DateTime.Now + "|CT|" + e.ChangeType + "|FP|" + e.FullPath + "|FN|" + eName;
                listChange.Add(changeEvent);
            }
            catch (Exception ex)
            {
                notifyIcon1.ShowBalloonTip(2, "Sync", "OnChanged error \n" + ex.Message, ToolTipIcon.Info);
            }
        }
        private void OnCreate(object source, FileSystemEventArgs e)
        {
            try
            {
                string eName = e.Name.Substring(e.Name.LastIndexOf("\\") + 1);
                if (!new sFileMethods().filterFile(eName))
                    return;
                string createEvent = "|CL|" + client + "|DT|" + DateTime.Now + "|CT|" + e.ChangeType + "|FP|" + e.FullPath + "|FN|" + eName;
                listChange.Add(createEvent);

            }
            catch (Exception ex)
            {
                notifyIcon1.ShowBalloonTip(2, "Sync", "OnCreated error \n" + ex.Message, ToolTipIcon.Info);
            }
        }
        private void OnDelete(object source, FileSystemEventArgs e)
        {
            try
            {

                string eName = e.Name.Substring(e.Name.LastIndexOf("\\") + 1);
                if (!new sFileMethods().filterFile(eName))
                    return;
                string deleteEvent = "|CL|" + client + "|DT|" + DateTime.Now + "|CT|" + e.ChangeType + "|FP|" + e.FullPath + "|FN|" + eName;
                listChange.Add(deleteEvent);
            }
            catch (Exception ex)
            {
                notifyIcon1.ShowBalloonTip(2, "Sync", "OnDeleted error \n" + ex.Message, ToolTipIcon.Info);
            }
        }
        private void OnRenamed(object source, RenamedEventArgs e)
        {
            try
            {
                string eOldName = e.OldName.Substring(e.OldName.LastIndexOf("\\") + 1);
                string eName = e.Name.Substring(e.Name.LastIndexOf("\\") + 1);
                if (!new sFileMethods().filterFile(eName))
                    return;
                string renameEvent = "|CL|" + client + "|DT|" + DateTime.Now + "|CT|" + e.ChangeType + "|OFP|" + e.OldFullPath + "|OFN|" + eOldName + "|NFP|" + e.FullPath + "|NFN|" + eName;
                listChange.Add(renameEvent);
            }
            catch (Exception ex)
            {
                notifyIcon1.ShowBalloonTip(2, "Sync", "OnRenamed error \n" + ex.Message, ToolTipIcon.Info);
            }
        }
        private void Main_Load(object sender, EventArgs e)
        {
            loadServer();
            loadListFolder();
        }
        private void btnAddFolder_Click(object sender, EventArgs e)
        {
            new sFileMethods().checkFileExist(configFile);
            using (FolderBrowserDialog fbd = new FolderBrowserDialog())
            {
                if (fbd.ShowDialog() == DialogResult.OK)
                {
                    File.AppendAllText(configFile, Environment.NewLine + "path :" + fbd.SelectedPath);
                    loadListFolder();
                    Thread thrd = new Thread(thrdCheck);
                    thrd.Start();
                }
            }
        }
        private void btnDel_Click(object sender, EventArgs e)
        {
            if (listFolder.Items.Count == 0)
                return;
            new sFileMethods().checkFileExist(configFile);
            string value = listFolder.FocusedItem.Text;
            File.Create(configFileTmp).Close();
            using (StreamReader sr = new StreamReader(configFile))
            {
                string line;
                listFolder.Items.Clear();
                while ((line = sr.ReadLine()) != null)
                {

                    string path;
                    if (line.StartsWith("path :"))
                    {
                        path = line.Substring(line.LastIndexOf("path :") + 6, line.Length - line.LastIndexOf("path :") - 6);
                        if (path != value)
                        {
                            {
                                File.AppendAllText(configFileTmp, Environment.NewLine + path);
                            }
                        }
                    }
                }

            }
            File.Delete(configFile);
            File.Move(configFileTmp, configFile);
            loadListFolder();
            Thread thrd = new Thread(thrdCheck);
            thrd.Start();
        }
        private void btnOpenFolder_Click(object sender, EventArgs e)
        {
            if (listFolder.Items.Count == 0)
                return;
            string value = listFolder.FocusedItem.Text;
            {
                System.Diagnostics.Process sdp = new System.Diagnostics.Process();
                sdp.StartInfo.FileName = value;
                sdp.Start();
            }
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            string s = sci.pathClient;
            asyncToClient();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (sms.error != "")
            {
                showNotify(sms.error);
                sms.error = "";
            }
            if (sms.success != "")
            {
                showNotify(sms.success);
                sms.success = "";
            }
        } 
    }
}
